package com.nb82.bean.im;

import java.net.InetSocketAddress;

import javax.net.ssl.SSLContext;

import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;
import org.apache.mina.filter.ssl.SslFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.nb82.bean.im.handler.CallBack;
import com.nb82.bean.im.pro.CodecFactory;
import com.nb82.bean.im.pro.MessageType;
import com.nb82.bean.im.pro.PackageHead;
import com.nb82.bean.im.ssl.BogusSslContextFactory;

/**
 * 
 * @author cxd
 */

public class ImService {
	public static NioSocketConnector connector;

	// 30����?
	private static final int IDELTIMEOUT = 30;
	// 15�뷢��һ��������
	private static final int HEARTBEATRATE = 15;

	private static final String HEARTBEATREQUEST = "HEARTBEATREQUEST";
	private static final String HEARTBEATRESPONSE = "HEARTBEATRESPONSE";

	private static IoSession session;

	private static IMHandler imhandler;
	
	private static String HOST;
	private static  int PORT;
	
	private static NioSocketConnector getAcceptor() {
		if (null == connector) {
			// ������������server�˵�Socket����
			connector = new NioSocketConnector();
		}
		return connector;
	}

	public ImService() {
		getAcceptor();
	}

	public static void main(String[] args) {
		connect("localhost",10010);
	}
	
	public static boolean connect(String host ,int port) {
		if (session != null && session.isConnected()) {
			throw new IllegalStateException(
					"Already connected. Disconnect first.");
		}
		if (callBack == null) {
			throw new IllegalStateException(
					" please setCallBack  before init it!");
		}
		HOST = host;
		PORT = port;
		try {
			connector = getAcceptor();
			//connector.getFilterChain().addLast("mdc", new MdcInjectionFilter());

			connector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,
					IDELTIMEOUT);
			connector.getSessionConfig().setKeepAlive(true);
			connector.getSessionConfig().setMinReadBufferSize(2048);
			connector.getSessionConfig().setSendBufferSize(2048);
			connector.getFilterChain().addLast("codec",
					new ProtocolCodecFilter(new CodecFactory()));
			if (false) {
				SSLContext sslContext = BogusSslContextFactory
						.getInstance(false);
				SslFilter sslFilter = new SslFilter(sslContext);
				sslFilter.setUseClientMode(true);
				connector.getFilterChain().addFirst("sslFilter", sslFilter);
			}

			// add handler

			KeepAliveMessageFactory heartBeatFactory = new KeepAliveMessageFactoryImpl();
			KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory,
					IdleStatus.BOTH_IDLE,new KeepAliveRequestTimeoutHandlerImpl());

			// �����Ƿ�forward����һ��filter
			heartBeat.setForwardEvent(true);
			// ��������Ƶ��
			heartBeat.setRequestInterval(HEARTBEATRATE);
			connector.getFilterChain().addLast("heartbeat", heartBeat);
			
			connector.setHandler(new IMHandler());//192.168.0.80
			ConnectFuture future1 = connector.connect(new InetSocketAddress(HOST,PORT));
			future1.awaitUninterruptibly();
			if (!future1.isConnected()) {
				return false;
			}
			session = future1.getSession();
			return true;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public IMHandler getImhandler() {
		return imhandler;
	}

	public void setImhandler(IMHandler handler) {
		imhandler = handler;
	}

	public static CallBack getCallBack() {
		return callBack;
	}

	public static void setCallBack(CallBack callBack1) {
		callBack = callBack1;
	}
	
	
	/*

	private static class KeepAliveMessageFactoryImpl implements
			KeepAliveMessageFactory {

		@Override
		public boolean isRequest(IoSession session, Object message) {
			System.out.println("������������Ϣ: " + message);
			if (message.equals(HEARTBEATREQUEST))
				return true;
			return false;
		}

		@Override
		public boolean isResponse(IoSession session, Object message) {
			// LOG.info("��Ӧ��������Ϣ: " + message);
			// if(message.equals(HEARTBEATRESPONSE))
			// return true;
			return false;
		}

		@Override
		public Object getRequest(IoSession session) {
			System.out.println("����Ԥ����Ϣ: " + HEARTBEATREQUEST);
			/** ����Ԥ�����? *
			return HEARTBEATREQUEST;
		}

		@Override
		public Object getResponse(IoSession session, Object request) {
			System.out.println("��ӦԤ����Ϣ: " + HEARTBEATREQUEST);
			/** ����Ԥ�����? *
			//HEARTBEATRESPONSE
			return null;
			// return null;
		}

	}
	*/

	// private static IMHandler imhandler = IMHandler.getInstance();
	static class IMHandler implements IoHandler {
		static final IMHandler handler = new IMHandler();

		public static IMHandler getInstance() {
			return handler == null ? new IMHandler() : handler;
		}

		@Override
		public void sessionCreated(IoSession session) throws Exception {
			System.out.println("sessionCreated");
			if (callBack != null) {
				callBack.sessionCreated(session);
			}
		}

		@Override
		public void sessionOpened(IoSession session) throws Exception {
			System.out.println("sessionOpened");
			if (callBack != null) {
				callBack.sessionOpened(session);
			}

		}

		@Override
		public void sessionClosed(IoSession session) throws Exception {
			System.out.println("IMHandler.sessionClosed() ====>"+session.toString()
					+ " ,  it will connect agen");
			if (callBack != null) {
				callBack.sessionClosed(session);
			}
			// ImService.this.connect();
			ImService.connect(HOST,PORT);
		}

		@Override
		public void sessionIdle(IoSession session, IdleStatus status)
				throws Exception {
			System.out.println("sessionIdle");
			if (callBack != null) {
				callBack.sessionIdle(session, status);
			}
		}

		@Override
		public void exceptionCaught(IoSession session, Throwable cause)
				throws Exception {
			System.out.println("exceptionCaught");
			if (callBack != null) {
				callBack.exceptionCaught(session, cause);
			}

		}

		@Override
		public void messageReceived(IoSession session, Object message)
				throws Exception {
			System.out.println(message);
			if (message instanceof PackageHead) {
				if (((PackageHead) message).getContentType() == MessageType.HEART_BEAT_ACK) {
					return;
				}
				if (callBack != null) {
					callBack.messageReceived(session, message);
				}
			}
		}

		@Override
		public void messageSent(IoSession session, Object message)
				throws Exception {
			System.out.println(message);
			if (callBack != null) {
				callBack.messageSent(session, message);
			}
		}

	}

	private static CallBack callBack;
	
	
	

	/***
	 * @ClassName: KeepAliveMessageFactoryImpl
	 * @Description: �ڲ��࣬ʵ����������
	 * @author Minsc Wang ys2b7_hotmail_com
	 * @date 2011-3-7 ����04:09:02
	 * 
	 */
	private static class KeepAliveMessageFactoryImpl implements
			KeepAliveMessageFactory {
		private static final Logger LOG = LoggerFactory
				.getLogger(KeepAliveMessageFactoryImpl.class);
		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.apache.mina.filter.keepalive.KeepAliveMessageFactory#getRequest
		 * (org.apache.mina.core.session.IoSession)
		 */
		@Override
		public Object getRequest(IoSession session) {
			LOG.info("����Ԥ�����?" + HEARTBEATREQUEST);
			/** ����Ԥ�����? */
			//HEARTBEATREQUEST
			PackageHead head = PackageHead.createHartResponse(HEARTBEATREQUEST);
			return head;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.apache.mina.filter.keepalive.KeepAliveMessageFactory#getResponse
		 * (org.apache.mina.core.session.IoSession, java.lang.Object)
		 */
		@Override
		public Object getResponse(IoSession session, Object request) {
			LOG.info("�õ�����");
			return null;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.apache.mina.filter.keepalive.KeepAliveMessageFactory#isRequest
		 * (org.apache.mina.core.session.IoSession, java.lang.Object)
		 */
		@Override
		public boolean isRequest(IoSession session, Object message) {
			LOG.info("�Ƿ���������: " + message);
			if (message instanceof PackageHead) {
				if(((PackageHead)message).getPackageBodyContent().equals(HEARTBEATREQUEST)){
					return true;
				}
			}
			
			
			//if(message.equals(HEARTBEATREQUEST))
			//	return true;
			return false;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.apache.mina.filter.keepalive.KeepAliveMessageFactory#isResponse
		 * (org.apache.mina.core.session.IoSession, java.lang.Object)
		 */
		@Override
		public boolean isResponse(IoSession session, Object message) {
			LOG.info("�Ƿ���������: " + message);
			if (message instanceof PackageHead) {
				if(((PackageHead)message).getPackageBodyContent().equals(HEARTBEATRESPONSE)){
					return true;
				}
			}
			//if(message.equals(HEARTBEATRESPONSE))
			//	return true;
			return false;
		}

	}

	/***
	 * @ClassName: KeepAliveRequestTimeoutHandlerImpl
	 * @Description: ��������ʱʱ�Ĵ���Ҳ������Ĭ�ϴ��� ����like
	 *               KeepAliveRequestTimeoutHandler.LOG�Ĵ���
	 * @author Minsc Wang ys2b7_hotmail_com
	 * @date 2011-3-7 ����04:15:39
	 * 
	 */
	private static class KeepAliveRequestTimeoutHandlerImpl implements
			KeepAliveRequestTimeoutHandler {
		 private final Logger LOGGER = LoggerFactory.getLogger(KeepAliveRequestTimeoutHandlerImpl.class);
		/*
		 * (non-Javadoc)
		 * 
		 * @seeorg.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler#
		 * keepAliveRequestTimedOut
		 * (org.apache.mina.filter.keepalive.KeepAliveFilter,
		 * org.apache.mina.core.session.IoSession)
		 */
		@Override
		public void keepAliveRequestTimedOut(KeepAliveFilter filter,
				IoSession session) throws Exception {
			LOGGER.info("������ʱ��");
		}

	}
}
